from xtquant import xtdata
from datetime import datetime
import pandas as pd
from typing import Dict, Optional
from 基础配置 import settings
from 公共函数 import update_stock_data
from 组件.notice import show_notification_thread, init_notification_system
from 组件.logger import Logger
from 指标.数据预热 import WarmupManager, data_processor
from 指标.日内九转 import IndependentNineTurnCalculator
from 指标.波动率 import ATRCalculator
from 指标.RSI import IndependentRSICalculator
from 指标.VMA import IndependentVMACalculator
from 指标.波动区间 import UpDownCalculator
from 指标.MACD import MACDMonitor
from 指标.MACD配置 import MACDConfig


class MarketMonitor:
    ##初始化
    def __init__(self, trader=None, log_callback=None, trade_cmd_queue=None):
        self.stock_codes = [s["all_code"] for s in settings.STOCK_CODE]
        self.period = "tick"  # 主数据流仍使用tick
        # RSI计算器现在完全独立，不需要订阅
        self.stock_type = {stock["all_code"]: stock["name"] for stock in settings.STOCK_CODE}
        self.log_callback = log_callback
        self._running = False
        self.trader = trader
        self.trade_cmd_queue = trade_cmd_queue
        
        # 初始化通知系统（包括音频播放器）
        init_notification_system()

        # 九转重复买入保护时间（分钟）
        self.nine_turn_buy_protection_minutes = 10
        
        # 日内九转计算器（完全独立，直接获取历史数据计算，无需预热）
        self.nine_turn = IndependentNineTurnCalculator(
            compare_offset=4, 
            required_bars=9, 
            verbose=True, 
            restrict_session=True,
            xtdata=xtdata
        )
        print(f"✅ 九转指标初始化完成: compare_offset=4, required_bars=9, verbose=True, restrict_session=True")
        print(f"✅ 九转重复买入保护时间: {self.nine_turn_buy_protection_minutes} 分钟")
        # ATR 波动率计算器（用于金叉买入时的波动过滤）
        self.atr_calculator = ATRCalculator(xtdata, lookback=settings.ATR_LOOKBACK, method='ema', cache_ttl_seconds=10, verbose=False)
        # RSI 计算器（完全独立，直接获取历史数据计算，无需预热）
        self.rsi_calculator = IndependentRSICalculator(period=5, xtdata=xtdata)
        # 区间波动计算器
        self.updown_calculator = UpDownCalculator()
        # 日志记录器
        self.logger = Logger()
        # MACD监控器（包含计算器和信号管理）
        self.macd_monitor = MACDMonitor(xtdata, self.stock_codes, self.stock_type)

        self._minute_bucket: Dict[str, str] = {}
        self._minute_close: Dict[str, float] = {}
        
        # 是否在启动时预热指标数据（下载当日tick并聚合分钟，RSI除外）
        self.enable_warmup: bool = True
        
        # 预热数据管理器
        self.warmup_manager = WarmupManager(xtdata, self.stock_codes, self.stock_type, self.log_callback)
        
        # VMA成交量指标（使用独立的VMA计算器）
        self.vma_calculator = IndependentVMACalculator(period=10, factor=1.2, xtdata=xtdata)


        
        # VMA调试开关（设为True可查看详细VMA信息）
        self._debug_vma = False
        
        # 添加信号状态跟踪，避免重复提示和下单
        self.signal_status = {code: {
            "last_golden_cross": None, 
            "last_death_cross": None,
            "last_nine_turn_buy": None,
            "last_nine_turn_sell": None
        } for code in self.stock_codes}
        
        # 九转信号时间保护：记录每个股票最后一次九转信号的时间
        self.nine_turn_signal_time = {code: {
            "last_buy_time": None,
            "last_sell_time": None
        } for code in self.stock_codes}

        # MACD信号检查间隔（每N个tick检查一次，与行情监控2.py保持一致）
        self.macd_check_interval = MACDConfig.TICK_CHECK_INTERVAL
        # 注意：tick计数器现在由MACD监控器统一管理
        # self._tick_counters: Dict[str, int] = {} # 用于记录每个股票的tick计数
        
        # 预初始化所有股票的tick计数器（现在由MACD监控器管理）
        # for stock_code in self.stock_codes:
        #     self._tick_counters[stock_code] = 0
        
        # 初始化计数器调试信息
        print(f"✅ MACD检查间隔设置为: {self.macd_check_interval} tick")
        print(f"✅ 已为 {len(self.stock_codes)} 只股票配置MACD监控")
        print(f"✅ MACD监控器将统一管理tick计数器和缓存")

    # RSI计算器现在完全独立，不需要分钟数据回调
    
    ##订阅tick回调
    def quote_callback(self, data):
        for stock_code, stock_data in data.items():
            stock_name = self.stock_type.get(stock_code)

            # 取最新一笔：time 最大
            data0 = self._get_latest_tick_data(stock_data)

            last_price = data0.get('lastPrice')
            timestamp = data0.get('time')
            volume = data0.get('volume', 0)

            # 数据验证
            if last_price is None or timestamp is None:
                self.log(f"⚠️ {stock_name} 数据无效: price={last_price}, timestamp={timestamp}")
                continue

            # 维护tick计数器（现在由MACD监控器统一管理）
            # if stock_code not in self._tick_counters:
            #     self._tick_counters[stock_code] = 0
            # self._tick_counters[stock_code] += 1
            
            # 使用MACD监控器统一管理tick计数器
            current_tick_count = self.macd_monitor.update_tick_counter(stock_code)
            
            # 添加计数器调试信息（每100个tick记录一次）
            if current_tick_count % 100 == 0:
                self.log(f"📊 {stock_code} tick计数器更新: {current_tick_count} (MACD检查间隔: {self.macd_check_interval})")
            
            # 添加首次tick的调试信息
            if current_tick_count == 1:
                self.log(f"🎯 {stock_code} 首个tick，计数器已初始化")

            # 计算所有指标
            indicators = self._calculate_all_indicators(stock_code, stock_name, last_price, timestamp, stock_data,volume)

            # 打印指标结果
            self._print_indicators(stock_code, stock_name, last_price, indicators, timestamp)

            # 将指标结果传给信号判断函数
            self.check_buy_sell(stock_code, stock_name, last_price, indicators)

            # 更新股票数据
            update_stock_data(
                stock_code,
                now_price=last_price,
                macd=indicators.get('macd', ''),
                updown_id=indicators.get('updown_id', 0),
                rsi=indicators.get('rsi', None)
            )

    ##计算所有技术指标
    def _calculate_all_indicators(self, stock_code: str, stock_name: str, last_price: float, timestamp, stock_data, volume):
        """计算所有技术指标"""
        indicators = {}
        
        # 1. VMA成交量指标（独立计算，不依赖tick数据）
        try:
            # 获取最新VMA值和成交量分析
            vma_value = self.vma_calculator.get_latest_vma(stock_code)
            volume_analysis = self.vma_calculator.get_volume_analysis(stock_code)
        except Exception as e:
            vma_value = None
            volume_analysis = None
            self.log(f"⚠️ {stock_code} VMA处理异常: {e}")

        # 存储VMA相关数据到indicators中
        indicators['vma_value'] = vma_value
        indicators['volume_analysis'] = volume_analysis
        
        # 2. 分钟聚合（用于其他指标计算）
        try:
            minute_key = data_processor.to_minute_bucket(timestamp)
            if minute_key is not None:
                # 仅更新当前分钟的收盘价，用于其他指标计算
                self._minute_close[stock_code] = float(last_price)
                self._minute_bucket[stock_code] = minute_key
        except Exception as e:
            self.log(f"⚠️ {stock_code} 分钟聚合异常: {e}")
        
        # 3. RSI指标（完全独立，直接获取最新值）
        try:
            rsi = self.rsi_calculator.get_latest_rsi(stock_code)
        except Exception as e:
            rsi = None
            self.log(f"⚠️ {stock_code} RSI获取异常: {e}")
        
        indicators['rsi'] = rsi
        

        
        # 4. MACD指标（按间隔触发，与行情监控2.py保持一致）
        macd = ""
        if stock_code not in ("513130.SH", "513061.SH"):
            try:
                # 使用MACD监控器统一管理的tick计数器
                current_tick_count = self.macd_monitor.get_tick_counter(stock_code)
                
                # 按间隔触发MACD计算（与行情监控2.py保持一致）
                if current_tick_count % self.macd_check_interval == 0:
                    self.log(f"🔄 {stock_code} 第{current_tick_count}个tick，开始计算MACD...")
                    
                    # 在回测模式下，传递回测日期给MACD计算器
                    trade_date = getattr(self, '_current_trade_date', None)
                    
                    # 添加更多调试信息
                    self.log(f"🔍 {stock_code} MACD计算参数: tick_count={current_tick_count}, interval={self.macd_check_interval}, trade_date={trade_date}")
                    
                    try:
                        # 使用MACD监控器的统一方法
                        macd = self.macd_monitor.check_macd_signals(stock_code, last_price, trade_date)
                        self.log(f"✅ {stock_code} MACD计算成功，结果: {macd}")
                    except Exception as macd_error:
                        self.log(f"❌ {stock_code} MACD计算器内部异常: {macd_error}")
                        import traceback
                        traceback.print_exc()
                        macd = ""
                else:
                    # 不在检查间隔时，记录调试信息（可选）
                    if current_tick_count % 100 == 0:  # 每100个tick记录一次
                        self.log(f"📊 {stock_code} 第{current_tick_count}个tick，距离下次MACD计算还需{self.macd_check_interval - (current_tick_count % self.macd_check_interval)}个tick")
                
            except Exception as e:
                self.log(f"❌ {stock_code} MACD计算外层异常: {e}")
                import traceback
                traceback.print_exc()
                macd = ""
        
        indicators['macd'] = macd
        
        # 5. 日内九转指标（获取上一分钟的完整信号，避免当前分钟数据不完整）
        try:
            # 获取上一分钟的完整信号
            nine_turn_signal = self.nine_turn.get_previous_minute_signal(stock_code)
            if nine_turn_signal:
                self.log(f"🔍 {stock_code} 上一分钟九转信号: {nine_turn_signal}")
            indicators['nine_turn'] = nine_turn_signal
        except Exception as e:
            self.log(f"⚠️ {stock_code} 九转信号获取异常: {e}")
            indicators['nine_turn'] = ""
        
        # 6. 波动区间指标
        updown_id = 0
        if stock_code in ("513130.SH", "513061.SH"):
            try:
                updown_id = self.updown_calculator.updown_watch_tick(stock_code, stock_data)
            except Exception as e:
                self.log(f"⚠️ {stock_code} 波动区间计算异常: {e}")
        indicators['updown_id'] = updown_id
        
        # 7. ATR波动率指标
        atr_ratio = None
        try:
            atr = self.atr_calculator.calculate_atr(stock_code, last_price)
            if atr is not None and atr > 0 and last_price:
                atr_ratio = atr / last_price
        except Exception as e:
            self.log(f"⚠️ {stock_code} ATR计算异常: {e}")
        indicators['atr_ratio'] = atr_ratio
        
        # 8. VMA指标（成交量放大判断）
        vma = False
        try:
            # 使用VMA计算器检查成交量是否放大
            surge_result = self.vma_calculator.check_volume_surge(stock_code)
            vma = surge_result.get('is_surge', False)
            
            # 记录VMA判断结果
            if surge_result.get('is_surge'):
                self.log(f"📈 {stock_code} VMA成交量放大: {surge_result.get('message', '')}")
            else:
                # 可选：记录非放大状态（调试用）
                if hasattr(self, '_debug_vma') and self._debug_vma:
                    self.log(f"📊 {stock_code} VMA状态: {surge_result.get('message', '')}")
                # 记录简要状态（即使调试关闭也显示）
                elif surge_result.get('message'):
                    self.log(f"📊 {stock_code} VMA: {surge_result.get('message', '')}")
                    
        except Exception as e:
            self.log(f"⚠️ {stock_code} VMA判断异常: {e}")
        indicators['vma'] = vma

        
        return indicators
    ##打印所有指标结果
    def _print_indicators(self, stock_code: str, stock_name: str, last_price: float, indicators: dict, timestamp=None):
        """打印所有指标结果"""
        try:
            # 显示当前时间
            current_time = datetime.now().strftime('%H:%M:%S')
            print(f"\n📊 [{current_time}] {stock_name}({stock_code}) - 价格: {last_price}")

            # 显示RSI指标
            rsi = indicators.get('rsi')
            rsi_str = f"{rsi:.2f}" if rsi is not None else "N/A"
            print(f"   RSI: {rsi_str}")

            # 显示VMA指标
            vma_value = indicators.get('vma_value')
            volume_analysis = indicators.get('volume_analysis')
            
            if vma_value and volume_analysis:
                current_vol = volume_analysis.get('current_volume', 0)
                last_valid_vol = volume_analysis.get('last_valid_volume', 0)
                volume_ratio = volume_analysis.get('volume_ratio', 0)
                trading_status = volume_analysis.get('trading_status', '未知')
                
                print(f"   VMA: {vma_value:.0f}")
                print(f"   成交量: 当前={current_vol:.0f}, 最近有效={last_valid_vol:.0f}, 倍数: {volume_ratio:.2f}, 状态: {trading_status}")
            else:
                print(f"   VMA: N/A")
                
            # 显示九转信号状态
            nine_turn_signal = indicators.get('nine_turn', '')
            if nine_turn_signal:
                print(f"   九转: {nine_turn_signal}")
                
                # 显示九转保护时间信息
                last_buy_time = self.nine_turn_signal_time[stock_code]["last_buy_time"]
                if last_buy_time is not None:
                    time_diff = (datetime.now() - last_buy_time).total_seconds() / 60
                    remaining_time = max(0, self.nine_turn_buy_protection_minutes - time_diff)
                    if remaining_time > 0:
                        print(f"   九转保护: 距离下次可买入还需 {remaining_time:.1f} 分钟")
                    else:
                        print(f"   九转保护: 可以买入")
            else:
                print(f"   九转: 无信号")

                
        except Exception as e:
            self.log(f"⚠️ {stock_code} 指标打印异常: {e}")
            import traceback
            traceback.print_exc()


    ##触发买卖
    def check_buy_sell(self, stock_code: str, stock_name: str, last_price: float, indicators: dict):
        """根据指标结果判断是否发出买入卖出信号"""
        need_buy = False
        need_sell = False

        # 获取指标值
        rsi_value = indicators.get('rsi')
        macd = indicators.get('macd', '')
        atr_ratio = indicators.get('atr_ratio')
        vma = indicators.get('vma', False)

        # RSI超卖信号
        if rsi_value is not None and 5 >= rsi_value > 1:
            show_notification_thread("RSI买提示", f"{stock_name}RSI买")
            need_buy = True
            self.logger.log_signal(f"RSI超卖信号触发：{stock_code} RSI={rsi_value:.2f}")

        # MACD金叉信号
        if macd == "金叉":
            # 检查是否与上次金叉信号相同，避免重复提示和下单
            # 与行情监控2.py保持一致：使用MACD信号的时间和价格作为唯一标识
            # 这样可以避免每次tick都产生新的信号标识
            # 注意：这里需要从MACD信号中获取时间和价格，而不是使用当前tick的价格
            # 但由于我们在这里只能访问到last_price，所以暂时使用价格去重
            # 真正的去重逻辑应该在MACDMonitor中处理
            current_signal_key = f"金叉_{last_price}"
            last_signal = self.signal_status[stock_code]["last_golden_cross"]

            if current_signal_key == last_signal:
                # 这是重复的金叉信号，不执行操作
                return
            else:
                # 这是新的金叉信号，执行操作
                self.signal_status[stock_code]["last_golden_cross"] = current_signal_key
            print(f"{stock_name} 出现金叉")

            self.logger.log_signal(f"{stock_name} 出现金叉")
            can_buy = 0

            # ATR波动率过滤
            if atr_ratio is not None and atr_ratio > 0:
                threshold = max(0.0006, atr_ratio * 0.7)  # 动态阈值
                if atr_ratio > threshold:
                    can_buy += 1
                else:
                    self.logger.log_signal(
                        f"ATR波动率不符合：{stock_code} {last_price} {atr_ratio:.6f} {threshold:.6f}")
            else:
                # 无法获取ATR时，默认允许
                can_buy += 1

            # RSI过滤
            if rsi_value is not None and rsi_value > 0:
                if rsi_value < 30:
                    can_buy += 1
                else:
                    self.logger.log_signal(f"RSI不符合：{stock_code}:{rsi_value:.2f}")

            # VMA过滤
            if vma:
                can_buy += 1
            else:
                self.logger.log_signal(f"VMA不符合：{stock_code}")

            # 三个条件都满足才买入
            if can_buy == 3:
                need_buy = True
                try:
                    atr_ratio_str = f"{atr_ratio:.6f}" if atr_ratio is not None else "NA"
                    self.logger.log_signal(
                        f"买入触发：{stock_code} price={last_price} macd=金叉 rsi={rsi_value:.2f} atr_ratio={atr_ratio_str} vma={vma}")
                except Exception:
                    pass

        # 九转买入信号
        nine_turn_signal = indicators.get('nine_turn', '')
        if nine_turn_signal == "买入":
            current_time = datetime.now()
            
            # 1. 检查是否与上次九转买入信号相同，避免重复提示和下单
            current_signal_key = f"九转买_{last_price}"
            last_signal = self.signal_status[stock_code]["last_nine_turn_buy"]

            if current_signal_key == last_signal:
                # 这是重复的九转买入信号，不执行操作
                return
                
            # 2. 检查重复买入保护时间（10分钟内不重复买入）
            last_buy_time = self.nine_turn_signal_time[stock_code]["last_buy_time"]
            if last_buy_time is not None:
                time_diff = (current_time - last_buy_time).total_seconds() / 60  # 转换为分钟
                if time_diff < self.nine_turn_buy_protection_minutes:
                    self.log(f"⏰ {stock_code} 九转买入信号被保护时间过滤：距离上次买入仅 {time_diff:.1f} 分钟，需要等待 {self.nine_turn_buy_protection_minutes} 分钟")
                    return
                    
            # 3. 检查信号是否是最新的（避免重启后获取到过期信号）
            # 获取九转计算器的缓存时间信息
            try:
                analysis = self.nine_turn.get_nine_turn_analysis(stock_code)
                if analysis.get('cached', False):
                    # 如果是缓存数据，检查缓存时间
                    cache_time = getattr(self.nine_turn, '_cache_time', {}).get(stock_code)
                    if cache_time is not None:
                        cache_age_minutes = (current_time.timestamp() - cache_time) / 60
                        if cache_age_minutes > 2:  # 缓存超过2分钟，认为可能过期
                            self.log(f"⚠️ {stock_code} 九转信号可能过期：缓存时间 {cache_age_minutes:.1f} 分钟")
                            # 强制刷新数据
                            self.nine_turn.reset(stock_code)
                            # 重新获取信号
                            nine_turn_signal = self.nine_turn.get_previous_minute_signal(stock_code)
                            if nine_turn_signal != "买入":
                                self.log(f"🔄 {stock_code} 刷新后九转信号变为: {nine_turn_signal}")
                                return
            except Exception as e:
                self.log(f"⚠️ {stock_code} 检查九转信号时间异常: {e}")
            
            # 4. 通过所有检查，执行买入操作
            self.signal_status[stock_code]["last_nine_turn_buy"] = current_signal_key
            self.nine_turn_signal_time[stock_code]["last_buy_time"] = current_time
            
            show_notification_thread("九转提示", f"{stock_name}九转买")
            need_buy = True
            try:
                self.logger.log_signal(f"买入触发：{stock_code} 九转买 price={last_price} 时间: {current_time.strftime('%H:%M:%S')}")
            except Exception:
                pass

        # 九转卖出信号
        nine_turn_signal = indicators.get('nine_turn', '')
        if nine_turn_signal == "卖出":
            current_time = datetime.now()
            
            # 1. 检查是否与上次九转卖出信号相同，避免重复提示和下单
            current_signal_key = f"九转卖_{last_price}"
            last_signal = self.signal_status[stock_code]["last_nine_turn_sell"]

            if current_signal_key == last_signal:
                # 这是重复的九转卖出信号，不执行操作
                return
                
            # 2. 检查信号是否是最新的（避免重启后获取到过期信号）
            try:
                analysis = self.nine_turn.get_nine_turn_analysis(stock_code)
                if analysis.get('cached', False):
                    # 如果是缓存数据，检查缓存时间
                    cache_time = getattr(self.nine_turn, '_cache_time', {}).get(stock_code)
                    if cache_time is not None:
                        cache_age_minutes = (current_time.timestamp() - cache_time) / 60
                        if cache_age_minutes > 2:  # 缓存超过2分钟，认为可能过期
                            self.log(f"⚠️ {stock_code} 九转卖出信号可能过期：缓存时间 {cache_age_minutes:.1f} 分钟")
                            # 强制刷新数据
                            self.nine_turn.reset(stock_code)
                            # 重新获取信号
                            nine_turn_signal = self.nine_turn.get_previous_minute_signal(stock_code)
                            if nine_turn_signal != "卖出":
                                self.log(f"🔄 {stock_code} 刷新后九转信号变为: {nine_turn_signal}")
                                return
            except Exception as e:
                self.log(f"⚠️ {stock_code} 检查九转卖出信号时间异常: {e}")
            
            # 3. 通过所有检查，执行卖出操作
            self.signal_status[stock_code]["last_nine_turn_sell"] = current_signal_key
            self.nine_turn_signal_time[stock_code]["last_sell_time"] = current_time
            
            need_sell = True
            try:
                self.logger.log_signal(f"九转卖出信号触发：{stock_code} price={last_price} 时间: {current_time.strftime('%H:%M:%S')}")
            except Exception:
                pass

        # 死叉信号处理
        if macd == "死叉":
            # 检查是否与上次死叉信号相同，避免重复提示和下单
            # 与行情监控2.py保持一致：使用死叉信号和价格作为唯一标识
            # 这样可以避免每次tick都产生新的信号标识
            # 注意：这里需要从MACD信号中获取时间和价格，而不是使用当前tick的价格
            # 但由于我们在这里只能访问到last_price，所以暂时使用价格去重
            # 真正的去重逻辑应该在MACDMonitor中处理
            current_signal_key = f"死叉_{last_price}"
            last_signal = self.signal_status[stock_code]["last_death_cross"]

            if current_signal_key == last_signal:
                # 这是重复的死叉信号，不执行操作
                return
            else:
                # 这是新的死叉信号，执行操作
                self.signal_status[stock_code]["last_death_cross"] = current_signal_key

            need_sell = True
            try:
                self.logger.log_signal(f"死叉信号触发：{stock_code} price={last_price}")
            except Exception:
                pass

        # 执行交易操作
        if need_sell:
            self.execute_death_cross_sell(stock_code)
        if need_buy:
            self.execute_golden_cross_buy(stock_code, stock_name, last_price)

    ##触发买卖【回测专用】
    def check_buy_sell_back(self, stock_code: str, stock_name: str, last_price: float, indicators: dict):
        """根据指标结果判断是否发出买入卖出信号"""
        need_buy = False
        need_sell = False

        # 获取指标值
        rsi_value = indicators.get('rsi')
        macd = indicators.get('macd', '')
        atr_ratio = indicators.get('atr_ratio')
        vma = indicators.get('vma', False)

        # RSI超卖信号
        if rsi_value is not None and 5 >= rsi_value > 1:
            need_buy = True
            self.logger.log_signal(f"RSI超卖信号触发：{stock_code} RSI={rsi_value:.2f}")

        # MACD金叉信号
        if macd == "金叉":
            # 检查是否与上次金叉信号相同，避免重复提示和下单
            # 与行情监控2.py保持一致：使用MACD信号的时间和价格作为唯一标识
            # 这样可以避免每次tick都产生新的信号标识
            # 注意：这里需要从MACD信号中获取时间和价格，而不是使用当前tick的价格
            # 但由于我们在这里只能访问到last_price，所以暂时使用价格去重
            # 真正的去重逻辑应该在MACDMonitor中处理
            current_signal_key = f"金叉_{last_price}"
            last_signal = self.signal_status[stock_code]["last_golden_cross"]

            if current_signal_key == last_signal:
                # 这是重复的金叉信号，不执行操作
                return
            else:
                # 这是新的金叉信号，执行操作
                self.signal_status[stock_code]["last_golden_cross"] = current_signal_key

            self.logger.log_signal(f"{stock_name} 出现金叉")
            can_buy = 0

            # ATR波动率过滤
            if atr_ratio is not None and atr_ratio > 0:
                threshold = max(0.0006, atr_ratio * 0.7)  # 动态阈值
                if atr_ratio > threshold:
                    can_buy += 1
                else:
                    self.logger.log_signal(
                        f"ATR波动率不符合：{stock_code} {last_price} {atr_ratio:.6f} {threshold:.6f}")
            else:
                # 无法获取ATR时，默认允许
                can_buy += 1

            # RSI过滤
            if rsi_value is not None and rsi_value > 0:
                if rsi_value < 50:
                    can_buy += 1
                else:
                    self.logger.log_signal(f"RSI不符合：{stock_code}:{rsi_value:.2f}")

            # VMA过滤
            if vma:
                can_buy += 1
            else:
                self.logger.log_signal(f"VMA不符合：{stock_code}")

            # 三个条件都满足才买入
            if can_buy == 3:
                need_buy = True
                try:
                    atr_ratio_str = f"{atr_ratio:.6f}" if atr_ratio is not None else "NA"
                    self.logger.log_signal(
                        f"买入触发：{stock_code} price={last_price} macd=金叉 rsi={rsi_value:.2f} atr_ratio={atr_ratio_str} vma={vma}")
                except Exception:
                    pass

        # 九转买入信号
        nine_turn_signal = indicators.get('nine_turn', '')
        if nine_turn_signal == "买入":
            current_time = datetime.now()
            
            # 1. 检查是否与上次九转买入信号相同，避免重复提示和下单
            current_signal_key = f"九转买_{last_price}"
            last_signal = self.signal_status[stock_code]["last_nine_turn_buy"]

            if current_signal_key == last_signal:
                # 这是重复的九转买入信号，不执行操作
                return
                
            # 2. 检查重复买入保护时间（10分钟内不重复买入）
            last_buy_time = self.nine_turn_signal_time[stock_code]["last_buy_time"]
            if last_buy_time is not None:
                time_diff = (current_time - last_buy_time).total_seconds() / 60  # 转换为分钟
                if time_diff < self.nine_turn_buy_protection_minutes:
                    self.log(f"⏰ {stock_code} 九转买入信号被保护时间过滤：距离上次买入仅 {time_diff:.1f} 分钟，需要等待 {self.nine_turn_buy_protection_minutes} 分钟")
                    return
                    
            # 3. 通过所有检查，执行买入操作
            self.signal_status[stock_code]["last_nine_turn_buy"] = current_signal_key
            self.nine_turn_signal_time[stock_code]["last_buy_time"] = current_time
            
            need_buy = True
            try:
                self.logger.log_signal(f"买入触发：{stock_code} 九转买 price={last_price} 时间: {current_time.strftime('%H:%M:%S')}")
            except Exception:
                pass

        # 九转卖出信号
        nine_turn_signal = indicators.get('nine_turn', '')
        if nine_turn_signal == "卖出":
            current_time = datetime.now()
            
            # 1. 检查是否与上次九转卖出信号相同，避免重复提示和下单
            current_signal_key = f"九转卖_{last_price}"
            last_signal = self.signal_status[stock_code]["last_nine_turn_sell"]

            if current_signal_key == last_signal:
                # 这是重复的九转卖出信号，不执行操作
                return
                
            # 2. 通过所有检查，执行卖出操作
            self.signal_status[stock_code]["last_nine_turn_sell"] = current_signal_key
            self.nine_turn_signal_time[stock_code]["last_sell_time"] = current_time
            
            need_sell = True
            try:
                self.logger.log_signal(f"卖出触发：{stock_code} 九转卖 price={last_price} 时间: {current_time.strftime('%H:%M:%S')}")
            except Exception:
                pass

        # 死叉信号处理
        if macd == "死叉":
            # 检查是否与上次死叉信号相同，避免重复提示和下单
            # 与行情监控2.py保持一致：使用死叉信号和价格作为唯一标识
            # 这样可以避免每次tick都产生新的信号标识
            # 注意：这里需要从MACD信号中获取时间和价格，而不是使用当前tick的价格
            # 但由于我们在这里只能访问到last_price，所以暂时使用价格去重
            # 真正的去重逻辑应该在MACDMonitor中处理
            current_signal_key = f"死叉_{last_price}"
            last_signal = self.signal_status[stock_code]["last_death_cross"]

            if current_signal_key == last_signal:
                # 这是重复的死叉信号，不执行操作
                return
            else:
                # 这是新的死叉信号，执行操作
                self.signal_status[stock_code]["last_death_cross"] = current_signal_key

            need_sell = True
            try:
                self.logger.log_signal(f"死叉信号触发：{stock_code} price={last_price}")
            except Exception:
                pass

        return need_buy, need_sell

    ##买入
    def execute_golden_cross_buy(self, stock_code: str, stock_name: str, current_price: float) -> bool:
        try:
            # 检查是否在交易时间段内
            if not self._is_trading_time():
                return False
            
            # 执行金叉自动买入
            try:
                # 优先通过指令队列通知主线程执行买入（避免子进程直接触控交易对象）
                if self.trade_cmd_queue:
                    try:
                        trade_cmd = {
                            "action": "buy",
                            "code": stock_code,
                            "reason": "MACD金叉自动买入"
                        }
                        self.trade_cmd_queue.put(trade_cmd)
                        return True
                    except Exception as e:
                        self.log(f"❌ 发送交易指令到队列失败: {e}")
                        return False
                elif self.trader and hasattr(self.trader, 'callback') and self.trader.is_running():
                    try:
                        order_id = self.trader.callback.buy(stock_code)
                        if order_id:
                            return True
                        else:
                            return False
                    except Exception as e:
                        self.log(f"❌ 执行金叉自动买入异常: {e}")
                        return False
                else:
                    return False
            except Exception as e:
                self.log(f"❌ 执行金叉自动买入异常: {e}")
                return False
        except Exception as e:
            self.log(f"❌ 执行金叉自动买入异常: {e}")
            return False
    ##卖出
    def execute_death_cross_sell(self, stock_code: str) -> bool:
        try:

            # 优先通过指令队列通知主线程执行按代码平仓（避免子进程直接触控交易对象）
            if self.trade_cmd_queue:
                try:
                    trade_cmd = {
                        "action": "close_by_code",
                        "code": stock_code,
                        "reason": "MACD死叉自动平仓"
                    }
                    self.trade_cmd_queue.put(trade_cmd)
                    return True
                except Exception as e:
                    self.log(f"❌ 发送平仓指令到队列失败: {e}")
                    # 继续尝试备用路径

            # 备用路径：若在同进程且有 trader，可直接按代码平仓
            if self.trader and hasattr(self.trader, 'callback') and self.trader.is_running():
                try:
                    self.trader.callback.cancel_all_sell_orders(stock_code)
                    return True
                except Exception as e:
                    self.log(f"❌ 直接调用按代码平仓失败: {e}")
                    return False

            self.log(f"❌ 无法执行死叉平仓，缺少trade_cmd_queue或trader未就绪: {stock_code}")
            return False
        except Exception as e:
            self.log(f"❌ 执行死叉自动平仓异常: {e}")
            return False                                           
    ##检查当前是否在交易时间段内
    ##交易时间
    def _is_trading_time(self) -> bool:
        """使用data_processor检查当前是否在交易时间段内"""
        return data_processor.is_trading_time()

    ##分钟聚合
    def _to_minute_bucket(self, ts) -> Optional[str]:
        """使用data_processor进行分钟聚合"""
        return data_processor.to_minute_bucket(ts)
    ##上一分钟数据
    def _is_session_minute(self, minute_str: Optional[str]) -> bool:
        """使用data_processor判断是否为交易时段内的分钟"""
        return data_processor.is_session_minute(minute_str)
    ##前端日志
    def log(self, msg):
        """统一的日志记录方法：同时输出到控制台和文件"""
        print(msg)
        if self.log_callback:
            self.log_callback(msg)
    ##获取最新的tick
    def _get_latest_tick_data(self, stock_data):
        """
        获取最新的tick数据（按时间戳排序取最大值）

        Args:
            stock_data: tick数据，可能是单个dict或list

        Returns:
            dict: 最新的tick数据
        """
        try:
            if isinstance(stock_data, list) and stock_data:
                def _as_ts(x):
                    try:
                        t = x.get('time') if isinstance(x, dict) else None
                        if t is None:
                            return -1.0
                        if isinstance(t, (int, float)):
                            return float(t)
                        s = str(t)
                        if s.isdigit():
                            return float(s)
                        ts = pd.to_datetime(s, errors='coerce')
                        if pd.isna(ts):
                            return -1.0
                        return float(ts.timestamp() * 1000.0)
                    except Exception:
                        return -1.0

                # 返回时间戳最大的tick数据
                return max(stock_data, key=_as_ts)
            else:
                # 如果不是列表或者为空，返回第一个元素
                return stock_data[0] if stock_data else {}
        except Exception:
            # 异常情况下返回第一个元素
            return stock_data[0] if stock_data else {}

    ##启动
    def start(self):
        self.logger.log_signal(f"开启实时行情")
        self._running = True
        
        # 设置MACD监控器的日志回调
        self.macd_monitor.set_log_callbacks(
            log_callback=self.log_callback,
            signal_logger=self.logger.signal_logger if hasattr(self.logger, 'signal_logger') else None
        )

        # 执行预热数据加载（RSI除外，RSI完全独立计算）
        # 在回测模式下，传递回测日期给预热管理器
        trade_date = getattr(self, '_current_trade_date', None)
        print(f"🔥 开始预热指标数据（RSI除外），回测日期: {trade_date}")
        
        try:
            self.warmup_manager.warmup_all_indicators(
                nine_turn=self.nine_turn,
                rsi_calculator=self.rsi_calculator,  # 添加RSI计算器参数
                volume_solution=self.vma_calculator,  # 使用VMA计算器替代原来的solution
                macd_monitor=self.macd_monitor,
                enable_warmup=self.enable_warmup,
                trade_date=trade_date
            )
            print("✅ 指标预热完成")
        except Exception as e:
            print(f"❌ 指标预热失败: {e}")
            import traceback
            traceback.print_exc()

        # 订阅实时行情（tick级别）
        for code in self.stock_codes:
            xtdata.subscribe_quote(
                code,
                period=self.period,
                count=-1,
                callback=self.quote_callback
            )
            self.log(f"已订阅 {code} 的tick级别实时行情")
        
        # RSI计算器现在完全独立，不需要订阅分钟数据
            
        self.log(f"开始监听 {len(self.stock_codes)} 只股票的实时行情...")

        try:
            xtdata.run()  # 阻塞
        except KeyboardInterrupt:
            self.log("行情监控已手动停止")
        except Exception as e:
            self.log(f"行情监控异常: {e}")
        ##停止
    def stop(self):
        # 这里需要你根据xtdata的API实现停止订阅和run
        self._running = False
        self.log("行情监控已停止")

        
